import asyncio
import logging
import os
import random

import pytest
from dotenv import load_dotenv
from hypothesis import Phase, Verbosity, settings
from starkware.cairo.lang.instances import LAYOUTS

load_dotenv(override=True)
logging.getLogger("asyncio").setLevel(logging.ERROR)
logger = logging.getLogger()


def pytest_addoption(parser):
    parser.addoption(
        "--profile-cairo",
        action="store_true",
        default=False,
        help="compute and dump TracerData for the VM runner: True or False",
    )
    parser.addoption(
        "--proof-mode",
        action="store_true",
        default=False,
        help="run the CairoRunner in proof mode: True or False",
    )
    parser.addoption(
        "--layout",
        choices=list(LAYOUTS.keys()),
        default="starknet_with_keccak",
        help="The layout of the Cairo AIR.",
    )
    parser.addoption(
        "--seed",
        action="store",
        default=random.randint(0, 2**64 - 1),
        type=int,
        help="The seed to set random with.",
    )


@pytest.fixture(scope="session")
def event_loop():
    loop = asyncio.get_event_loop()
    yield loop
    loop.close()


@pytest.fixture(autouse=True, scope="session")
def seed(request, worker_id):
    """
    Set the seed for the random module.

    If a seed is provided in the command line, we use it to have pseudo-randomness
    across tests (i.e. deterministic tests).

    If no seed is provided, we use a random seed.

    The worker_id is used as a salt to avoid collisions between tests in different workers.
    """
    import random

    salt = abs(hash(worker_id))
    logger.info(f"Using salt {salt} for worker {worker_id}")

    seed = request.config.getoption("seed") + salt

    logger.info(f"Setting seed to {seed}")
    random.seed(seed)


pytest_plugins = ["tests.fixtures.starknet"]

settings.register_profile(
    "nightly",
    deadline=None,
    max_examples=1500,
    phases=[Phase.explicit, Phase.reuse, Phase.generate, Phase.target],
)
settings.register_profile(
    "ci",
    deadline=None,
    max_examples=100,
    phases=[Phase.explicit, Phase.reuse, Phase.generate, Phase.target],
)
settings.register_profile(
    "dev",
    deadline=None,
    max_examples=10,
    phases=[Phase.explicit, Phase.reuse, Phase.generate, Phase.target],
)
settings.register_profile(
    "debug",
    max_examples=10,
    verbosity=Verbosity.verbose,
    phases=[Phase.explicit, Phase.reuse, Phase.generate, Phase.target],
)
settings.load_profile(os.getenv("HYPOTHESIS_PROFILE", "default"))
logger.info(f"Using Hypothesis profile: {os.getenv('HYPOTHESIS_PROFILE', 'default')}")
